//    |  /           |
//    ' /   __| _` | __|  _ \   __|
//    . \  |   (   | |   (   |\__ `
//   _|\_\_|  \__,_|\__|\___/ ____/
//                   Multi-Physics
//
//  License:		 BSD License
//					 license: OptimizationApplication/license.txt
//
//  Main author:     Reza Najian Asl,
//                   Suneth Warnakulasuriya
//

// System includes

// External includes

// Project includes

// Application includes
#include "optimization_application_variables.h"

namespace Kratos
{
    //Auxilary field
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(AUXILIARY_FIELD);

    //linear function
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_LINEAR_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_LINEAR_D_CX);

    //symmetry plane
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_PLANE_SYMMETRY_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_PLANE_SYMMETRY_D_CX);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(NEAREST_NEIGHBOUR_POINT);
    KRATOS_CREATE_VARIABLE(double, NEAREST_NEIGHBOUR_DIST);
    KRATOS_CREATE_VARIABLE(int, NEAREST_NEIGHBOUR_COND_ID);

    //strain energy
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_1_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_1_D_CX);
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_2_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_2_D_CX);
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_3_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRAIN_ENERGY_3_D_CX);

    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_1_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_1_D_CD);

    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_2_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_2_D_CD);

    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_3_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_3_D_CD);


    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_1_D_FT);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_1_D_CT);

    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_2_D_FT);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_2_D_CT);

    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_3_D_FT);
    KRATOS_CREATE_VARIABLE(double, D_STRAIN_ENERGY_3_D_CT);

    //partitioning
    KRATOS_CREATE_VARIABLE(double, D_INTERFACE_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_INTERFACE_D_CD);
    KRATOS_CREATE_VARIABLE(double, D_PARTITION_MASS_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_PARTITION_MASS_D_CD);

    //mass
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_MASS_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_MASS_D_CX);
	KRATOS_CREATE_VARIABLE(double, D_MASS_D_FT);
    KRATOS_CREATE_VARIABLE(double, D_MASS_D_CT);
	KRATOS_CREATE_VARIABLE(double, D_MASS_D_PD);
    KRATOS_CREATE_VARIABLE(double, D_MASS_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_MASS_D_CD);

    //max overhang angle
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_MAX_OVERHANG_ANGLE_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_MAX_OVERHANG_ANGLE_D_CX);

    //stress
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRESS_D_X);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_STRESS_D_CX);
	KRATOS_CREATE_VARIABLE(double, D_STRESS_D_FD);
    KRATOS_CREATE_VARIABLE(double, D_STRESS_D_CD);

    // shape control
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(SX);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(CX);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_CX);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(D_X);

    // thickness control
    KRATOS_CREATE_VARIABLE(double,PT);
    KRATOS_CREATE_VARIABLE(double,PPT);
    KRATOS_CREATE_VARIABLE(double,FT);
    KRATOS_CREATE_VARIABLE(double,CT);
    KRATOS_CREATE_VARIABLE(double,D_CT);
    KRATOS_CREATE_VARIABLE(double,D_PT);
    KRATOS_CREATE_VARIABLE(double,D_PT_D_FT);
    KRATOS_CREATE_VARIABLE(double,D_PPT_D_FT);

    // density control
    KRATOS_CREATE_VARIABLE(double,PD);
    KRATOS_CREATE_VARIABLE(double,PE);
    KRATOS_CREATE_VARIABLE(double,D_PD_D_FD);
    KRATOS_CREATE_VARIABLE(double,D_PE_D_FD);
    KRATOS_CREATE_VARIABLE(double,FD);
    KRATOS_CREATE_VARIABLE(double,CD);
    KRATOS_CREATE_VARIABLE(double,D_CD);
    KRATOS_CREATE_VARIABLE(double,D_PD);

    // For implicit vertex-morphing with Helmholtz PDE
	KRATOS_CREATE_VARIABLE( Matrix, HELMHOLTZ_MASS_MATRIX );
	KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SURF_RADIUS_SHAPE );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_BULK_RADIUS_SHAPE );
	KRATOS_CREATE_VARIABLE( bool, COMPUTE_CONTROL_POINTS_SHAPE );
    KRATOS_CREATE_VARIABLE( double, ELEMENT_STRAIN_ENERGY );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SURF_POISSON_RATIO_SHAPE );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_BULK_POISSON_RATIO_SHAPE );
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( HELMHOLTZ_VARS_SHAPE);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( HELMHOLTZ_SOURCE_SHAPE);

    // for thickness optimization
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_VAR_THICKNESS );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SOURCE_THICKNESS );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_RADIUS_THICKNESS );

    // for topology optimization
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_VAR_DENSITY );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SOURCE_DENSITY );
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_RADIUS_DENSITY );
    KRATOS_CREATE_VARIABLE( bool, COMPUTE_CONTROL_DENSITIES );

    // For helholtz solvers
    KRATOS_CREATE_VARIABLE( bool, COMPUTE_HELMHOLTZ_INVERSE);
    KRATOS_CREATE_VARIABLE( bool, HELMHOLTZ_INTEGRATED_FIELD);
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_RADIUS);
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SCALAR);
    KRATOS_CREATE_VARIABLE( double, HELMHOLTZ_SCALAR_SOURCE);
    KRATOS_CREATE_VARIABLE( int, NUMBER_OF_SOLVERS_USING_NODES);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( HELMHOLTZ_VECTOR);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( HELMHOLTZ_VECTOR_SOURCE);

    //Adjoint RHS
	KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(ADJOINT_RHS);

    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(SHAPE);
    KRATOS_CREATE_VARIABLE(double, CROSS_AREA);
    KRATOS_CREATE_VARIABLE(double, DENSITY_SENSITIVITY);
    KRATOS_CREATE_VARIABLE(double, THICKNESS_SENSITIVITY);
    KRATOS_CREATE_VARIABLE(double, CROSS_AREA_SENSITIVITY);
    KRATOS_CREATE_VARIABLE(double, YOUNG_MODULUS_SENSITIVITY);
    KRATOS_CREATE_VARIABLE(double, POISSON_RATIO_SENSITIVITY);

    KRATOS_CREATE_VARIABLE(double, CUSTOM_DESIGN_VARIABLE);

    // do not expose the following variables to python. They are used
    // as temporary data holders. They can be changed
    // at any point of time in an analysis.
    // Hence, not recommended to be used for calculations
    // unless existing values on those variables are not of interest
    KRATOS_CREATE_VARIABLE(double, TEMPORARY_SCALAR_VARIABLE_1);
    KRATOS_CREATE_VARIABLE(double, TEMPORARY_SCALAR_VARIABLE_2);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TEMPORARY_ARRAY3_VARIABLE_1);
    KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TEMPORARY_ARRAY3_VARIABLE_2);

    KRATOS_CREATE_VARIABLE(std::vector<std::string>, MODEL_PART_STATUS);
}
